
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>  // must include stdio  for pvm3.h to compile correctly
#include <sys/times.h> /* for times system call */
#include <sys/time.h>  /* for gettimeofday system call */
#include <pthread.h>

#define BUFSIZE 32


/*#define DEBUG 1*/


//The main work routine
void *generateRandomNumbers(void *);  
double getMilliSeconds();


static long long int count; //Create global count variable
static int threadCount; //Create global thread count variable




/* The main work routine */


void *generateRandomNumbers(void *threadID)  
{
    long long int i; //Variable for looping
    long long int numberCount; //Variable that will hold how many random numbers the current thread should generate
    
        
    //Calculate how many numbers the current thread should generate based on
    //the number of threads to be used, the current thread ID and the total amount of numbers to be generated.
    
    if(*(int *)threadID != threadCount){ //If this isn't the last thread that will be created
      numberCount = count / threadCount; //Will truncate any decimal portion since all numbers are integers
    }
    else{ //If this is the last thread to be created
      numberCount = count - count / threadCount * (threadCount - 1); //A nice little algorithm to calculate how many numbers the final thread should calculate
    }
    
    
	
    struct random_data *rdata = (struct random_data *) malloc(sizeof(struct random_data));
    char *statebuf = (char*) malloc(sizeof(char) * BUFSIZE);

    int32_t value;

    initstate_r(*(int *)threadID, statebuf, BUFSIZE, rdata);
	
    //Seed the random number generator with the threadID, then increment
    srandom_r(*(int *)threadID,rdata);
	
    for (i = 0; i < numberCount; i++) {
		random_r(rdata, &value);
		printf("%d\n", value);
  	}
  	
    pthread_exit(NULL);
}


int main(int argc, char **argv)
{
    pthread_t *tid; //Create thread handle variable
	
	
    double timeStart = 0;
    double timeElapsed = 0;

    if (argc != 3) {
        fprintf(stderr, "Usage: %s <numberOfRandoms> <numThreads>\n" ,argv[0]);
        exit(1);
    }
    sscanf(argv[1],"%lld",&count); /* lld for long long int */
    
    threadCount = atoi(argv[2]); //Convert to integer

    timeStart = getMilliSeconds();	//And we are off
    
    //Create the threads.
    
      
    //Create variables and start the loop
    
    int i; //Looping Variable
    int *threadID; //Creates a pointer to pass to the generateRandomNumbers() function.
    
    
    
    
    
    tid = (pthread_t *) malloc(sizeof(pthread_t) * threadCount); //Reserve memory for thread handles
    for(i = 1; i <= threadCount; i++){
	//Create a thread with an id of "i"
	threadID = (int *) malloc(sizeof(int)); //Reserve memory in the heap for our threadID variable
	*threadID = i; //Set the value of our reserved memory
	pthread_create(&tid[i-1], NULL, generateRandomNumbers, (void *) threadID); //Create the thread
    }
    
    for (i=0; i<threadCount; i++){ //Wait for all threads to finish before continuing
     	pthread_join(tid[i], NULL);
    }
    
    
    
    printf("generated %lld random numbers\n", count);

    timeElapsed = getMilliSeconds() - timeStart;
    printf("Elapsed time:  %lf seconds\n",(double)(timeElapsed/1000.0));
    fflush(stdout);

    exit(0);
}
